package org.xuyuji.study.apache;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

/**
 * apache的工具包实现
 * @author xuyuji
 *
 */
public class FTPDemo {
	public static void main(String[] args) throws IOException {
		Client client = new Client("192.168.1.112", 21, "xuyuji", "123");
//		for(String str : client.getAllFilePath("/")){
//			System.out.println(str);
//		}
//		client.download("/tet.txt", "D://test.txt");
		client.upload("/home/tet2.txt", "D://test.txt");
	}
}

class Client{
	private static final int CONNECT_TIME_OUT = 5 * 1000;
	
	private static final int DATE_TIME_OUT = 3 * 60 * 1000;
	
	private FTPClient ftpClient = new FTPClient();
	
	private String ip;
	
	private int port;
	
	private String loginName;
	
	private String loginPassword;
	
	public Client(String ip, int port, String loginName, String loginPassword){
		this.ip = ip;
		this.port = port;
		this.loginName = loginName;
		this.loginPassword = loginPassword;
		
		/*
			ftp主动/被动模式
			主动：
			主动方式的FTP是这样的：客户端从一个任意的非特权端口N（N > 1024）连接到FTP服务器的命令端口，也就是21端口。
			然后客户端开始监听端口N+1，并发送FTP命令“port N+1”到FTP服务器。
			接着服务器会从它自己的数据端口（20）连接到客户端指定的数据端口（N+1）。
	
			被动：
			当开启一个 FTP连接时，客户端打开两个任意的非特权本地端口（N > 1024和N+1）。
			第一个端口连接服务器的21端口，但与主动方式的FTP不同，客户端不会提交PORT命令并允许服务器来回连它的数据端口，而是提交 PASV命令。
			这样做的结果是服务器会开启一个任意的非特权端口（P &gt; 1024），并发送PORT P命令给客户端。
			然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。
		*/
		ftpClient.setDefaultTimeout(DATE_TIME_OUT);	//连接命令端口无响应超时时间
		ftpClient.setDataTimeout(DATE_TIME_OUT);	//连接数据端口无响应超时时间
		ftpClient.setConnectTimeout(CONNECT_TIME_OUT);	//连接超时时间
		connect();
	}
	
	public void connect(){
		if(!ftpClient.isConnected()){
			try {
				ftpClient.connect(ip, port);
				ftpClient.login(loginName, loginPassword);
				ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
				System.out.println(ftpClient.getReplyString());
			} catch (IOException e) {
				System.out.println("连接" + ip + ":" + port + "失败!" + e.getMessage());
			}
		}
	}
	
	public boolean download(String remoteFilePath, String localFilePath) throws IOException{
		boolean result;
		OutputStream out = new FileOutputStream(new File(localFilePath));
		result = ftpClient.retrieveFile(remoteFilePath, out);
		out.close();
		return result;
	}
	
	public boolean upload(String remoteFilePath, String localFilePath) throws FileNotFoundException, IOException{
		boolean result;
		FileInputStream in = new FileInputStream(new File(localFilePath));
		result = ftpClient.storeFile(remoteFilePath, in);
		in.close();
		return result;
	}
	
	public List<String> getAllFilePath(String parentPath) throws IOException{
		List<String> list = new ArrayList<String>();
		if(ftpClient.isConnected()){
			getAllFilePath_(parentPath, list);
		}else{
			System.out.println("没有连接!");
		}
		return list;
	}
	
	private void getAllFilePath_(String parentPath, List<String> list) throws IOException{
		ftpClient.changeWorkingDirectory(parentPath);
		for(FTPFile ftpFile : ftpClient.listFiles()){
			if(ftpFile.isDirectory()){
				getAllFilePath_(parentPath + ftpFile.getName() + "/", list);
			}else{
				list.add(parentPath + ftpFile.getName());
			}
		}
	}
}
